package com.softtek.ibeacon.service.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import org.apache.log4j.Logger;

// This class should be used for all dir or file paths relative to the Application Server.
// The properties are defined in the file conf/agbs.properties ar have a sensitive default here.
public final class ConfigurationsProxyImpl
	implements ConfigurationsProxy {

    private static final Logger logger = Logger.getLogger(ConfigurationsProxy.class);
    // private static final String TRANSLATIONS_RESOURCE_PROPERTIES = "resources\\messages_en.properties";
    private static final String PROP_VAR_SYMBOL = "@";
    // PROPERTY_DEFAULTS
    private final Map<String, String> PROPERTY_DEFAULTS = new TreeMap<String, String>();
    private final Map<String, String> AGBS_PROPERTIES = new TreeMap<String, String>();
    // cached properties
    private Map<String, String> USED_DEPLOY_PROPERTIES;

    ConfigurationsProxyImpl() {
	super();
	long a = Calendar.getInstance().getTimeInMillis();
	initializeDefaultProperties();
	initializeCachedProperties();
	long b = Calendar.getInstance().getTimeInMillis();
	logger.debug("use time =" + (b - a));
    }

    // private File getAgsPropertiesFile() {
    // return new File(buildAgsSeamConfPath("agbs.properties"));
    // }
    // do not use getProperty here!!
    private void initializeDefaultProperties() {
	PROPERTY_DEFAULTS.clear();
	PROPERTY_DEFAULTS.put("DEPLOY_VERSION", System.getProperty("deploy.version", ""));
	String JBOSS_SERVER_HOME_DIR = System.getProperty("jboss.server.home.dir", "");
	logger.info("01 initializing default properties..." + JBOSS_SERVER_HOME_DIR + "/conf");
	PROPERTY_DEFAULTS.put("JBOSS_SERVER_HOME_DIR", JBOSS_SERVER_HOME_DIR);
	PROPERTY_DEFAULTS.put("AGBSSEAM_CONF_DIR", System.getProperty("agbs.conf.dir", JBOSS_SERVER_HOME_DIR + "/conf"));
	if (new File(JBOSS_SERVER_HOME_DIR + "/conf/AgbsSeam").exists()) {
	    PROPERTY_DEFAULTS.put("AGBSSEAM_CONF_DIR",
		    System.getProperty("agbs.conf.dir", JBOSS_SERVER_HOME_DIR + "/conf/AgbsSeam"));
	} else if (new File(JBOSS_SERVER_HOME_DIR + "/conf").exists()) {
	    PROPERTY_DEFAULTS.put("AGBSSEAM_CONF_DIR", System.getProperty("agbs.conf.dir", JBOSS_SERVER_HOME_DIR + "/conf"));
	}
	PROPERTY_DEFAULTS.put("AGBS_SEAM_SECURITY_DIR", buildAgsSeamConfPath("security"));
	PROPERTY_DEFAULTS.put("AUTO_LOGGEDIN_USER_NAMES", "bypass,testuser01,testuser02");
	PROPERTY_DEFAULTS.put("DEFAULT_ORACLE_DATE_FORMAT", "DD/MM/YYYY");
	PROPERTY_DEFAULTS.put("SECURITY_REGISTER_DIR", buildJBossServerPath("data", "agbs-security-register"));
	PROPERTY_DEFAULTS.put("MENU_LIST_XML_FILE_PATH", buildAgsSeamConfPath("AgbsActions.xml"));
	PROPERTY_DEFAULTS.put("ENABLE_BYPASS_QUICK_LOGIN", "false");
	PROPERTY_DEFAULTS.put("USED_DEPLOY_PROPERTIES", buildAgsSeamConfPath("used.deploy.properties"));
	PROPERTY_DEFAULTS.put("MONITORED_SERVER_LOG_FILE", buildJBossServerPath("log", "server.log"));
    }

    // -------------------------------------------------------------------------------------------------------------------------------------
    // to avoid synchronization problems and improve performance we initialize
    // some stuffs here
    // -------------------------------------------------------------------------------------------------------------------------------------
    private void initializeCachedProperties() {
    	USED_DEPLOY_PROPERTIES = new HashMap<String, String>();
    }

    // --------------------------------------------------------------------------------------------------------
    // INTERFACE
    // --------------------------------------------------------------------------------------------------------
    @Override
    public String getProperty(String name, String defaultValue) {
	String value = AGBS_PROPERTIES.containsKey(name) ? AGBS_PROPERTIES.get(name) : System.getProperty(name, defaultValue);
	String returnValue = replacePropertyValues(name, value);
	return returnValue;
    }

    @Override
    public String getJBossServerHomeDir() {
	return PROPERTY_DEFAULTS.get("JBOSS_SERVER_HOME_DIR");
    }

    @Override
    public String getAgsSeamConfDir() {
	return PROPERTY_DEFAULTS.get("AGBSSEAM_CONF_DIR");
    }

    @Override
    public List<String> getAutoLoggedInUsers() {
	String names = getProperty("AUTO_LOGGEDIN_USER_NAMES");
	if (names != null && names.length() > 0) {
	    return Arrays.asList(names.split(","));
	}
	return Collections.emptyList();
    }

    @Override
    public String getOracleDefaultDateFormat() {
	return getProperty("DEFAULT_ORACLE_DATE_FORMAT");
    }

    @Override
    public File getAgsSeamSecurityFile(String name) {
	return new File(getProperty("AGBS_SEAM_SECURITY_DIR").concat(File.separator).concat(name));
    }

    @Override
    public File getSecurityRegisterDir() {
	return new File(getProperty("SECURITY_REGISTER_DIR"));
    }

    @Override
    public File getReportResultsTemplate() {
	return new File(getProperty("REPORT_RESULTS_TEMPLATE"));
    }

    @Override
    public File getUploaderTempDir() {
	return new File(getProperty("UPLOADER_TEMPORARY_FILES_DIR"));
    }

    @Override
    public boolean enableBypassQuickLogin() {
	return getProperty("ENABLE_BYPASS_QUICK_LOGIN").equals("true");
    }

    @Override
    public Map<String, String> getUsedDeployProperties() {
	return USED_DEPLOY_PROPERTIES;
    }

    @Override
    public File getUploaderTemplate(String templateFileName) {
	return new File(buildAgsSeamConfPath(templateFileName));
    }

    @Override
    public File getLogFile() {
	return new File(getProperty("MONITORED_SERVER_LOG_FILE"));
    }
    
    @Override
    public String getDefaultRegionAGBS() {
	Properties prop = new Properties();
	try {
	    prop.load(new FileInputStream(buildAgsSeamConfPath("agbs.properties")));
	} catch (FileNotFoundException e) {
	    e.printStackTrace();
	} catch (IOException e) {
	    e.printStackTrace();
	}
	return prop.getProperty("DEFAULT_REGION_AGBS", "TW");
    }

    // --------------------------------------------------------------------------------------------------------
    // Helpers
    // --------------------------------------------------------------------------------------------------------
    private String getProperty(String name) {
	String value = System.getProperty(name, PROPERTY_DEFAULTS.get(name));
	return replacePropertyValues(name, value);
    }

    private String checkFileSeparator(String path) {
	return path.replace("/", File.separator).replace("\\", File.separator);
    }

    private String replacePropertyValues(String propName, String value) {
	if (value.contains(PROP_VAR_SYMBOL)) {
	    for (String name : PROPERTY_DEFAULTS.keySet()) {
		if (!name.equals(propName)) {
		    String varName = PROP_VAR_SYMBOL + "{" + name + "}";
		    value = value.replace(varName, getProperty(name));
		}
	    }
	}
	return value;
    }

    private String buildJBossServerPath(String... pathNodes) {
	StringBuffer path = new StringBuffer(getJBossServerHomeDir());
	for (String pathNode : pathNodes) {
	    path.append(File.separator);
	    path.append(pathNode);
	}
	return environmentSensitivePath(path.toString());
    }

    private String buildAgsSeamConfPath(String... pathNodes) {
	StringBuffer path = new StringBuffer(getAgsSeamConfDir());
	for (String pathNode : pathNodes) {
	    path.append(File.separator);
	    path.append(pathNode);
	}
	return environmentSensitivePath(path.toString());
    }

    private static String environmentSensitivePath(String jBossServerPath) {
	if (jBossServerPath != null && !jBossServerPath.startsWith("/app/") && !jBossServerPath.startsWith("/opt/")
		&& (jBossServerPath.startsWith("\\") || jBossServerPath.startsWith("/"))) {
	    return jBossServerPath.substring(1);
	}
	return jBossServerPath;
    }

    // --------------------------------------------------------------------------------------------------------
    // reportProperties
    // --------------------------------------------------------------------------------------------------------
    public void reportProperties() {
    }

    public Map<String, String> getAllProperties() {
	Map<String, String> properties = new TreeMap<String, String>();
	for (String name : PROPERTY_DEFAULTS.keySet()) {
	    properties.put(name, getProperty(name));
	}
	return properties;
    }

    // ------------------------------------------------------------------------------------------------------
    // Agbs Actions
    // ------------------------------------------------------------------------------------------------------
    @Override
    public String getMenuListXmlFilePath() {
	return checkFileSeparator(getProperty("MENU_LIST_XML_FILE_PATH"));
    }

    @Override
    public String getVersion() {
	return getProperty("DEPLOY_VERSION");
    }
}
